package com.ecommerce.controller;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ecommerce.common.CommonEnum;
import com.ecommerce.common.ResultBody;
import com.ecommerce.entity.Coupon;
import com.ecommerce.entity.CouponReceive;
import com.ecommerce.entity.UserDetail;
import com.ecommerce.service.CouponReceiveService;
import com.ecommerce.service.CouponService;
import com.ecommerce.service.UserDetailService;
import com.ecommerce.utils.WrapperUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;

/**
 * 优惠券Controller
 *
 * @author wang
 */
@RestController
@Api(value = "CouponController", tags = {"优惠券接口"})
@RequestMapping("/coupon")
@Log4j
public class CouponController {

    @Autowired
    private WrapperUtils wrapperUtils;

    @Autowired
    private CouponService couponService;

    @Autowired
    private UserDetailService userDetailService;

    @Autowired
    private CouponReceiveService couponReceiveService;

    /**
     * 查询优惠券列表
     *
     * @param coupon   优惠券
     * @param pageNum  页码
     * @param pageSize 条数
     * @return 优惠券列表
     */
    @ApiOperation(value = "查询优惠券列表", notes = "查询优惠券列表")
    @PostMapping(value = "/couponList")
    public ResultBody couponList(@RequestBody(required = false) Coupon coupon, @RequestParam Integer pageNum, @RequestParam Integer pageSize) {
        IPage<Coupon> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Coupon> wrapper = wrapperUtils.couponWrapper(coupon);
        wrapper.orderByDesc(Coupon::getCreateTime);
        return ResultBody.ok().data(couponService.page(page, wrapper));

    }

    /**
     * 创建优惠券
     *
     * @param coupon 优惠券
     * @return 创建优惠券情况
     */
    @ApiOperation(value = "创建优惠券", notes = "创建优惠券")
    @PostMapping(value = "/createCoupon")
    public ResultBody createCoupon(@RequestBody Coupon coupon) {
        coupon.setStatus(CommonEnum.SHELVES.getCode());
        coupon.setCreateTime(new Date());
        coupon.setDeleted("0");
        if (coupon.getReceiveType().equals(CommonEnum.NORMAL.getCode())) {
            coupon.setDeduction(0);
        }
        boolean save = couponService.save(coupon);
        if (save) {
            return ResultBody.ok().message("创建优惠券成功");
        } else {
            return ResultBody.error().message("创建优惠券失败");
        }
    }

    /**
     * 上架优惠券
     *
     * @param couponId 优惠券Id
     * @return 上架优惠券情况
     */
    @ApiOperation(value = "上架优惠券", notes = "上架优惠券")
    @PostMapping(value = "/shelvesCoupon")
    public ResultBody shelvesCoupon(@RequestParam String couponId) {
        LambdaUpdateWrapper<Coupon> couponWrapper = new LambdaUpdateWrapper<>();
        couponWrapper.eq(Coupon::getCouponId, couponId).set(Coupon::getStatus, CommonEnum.SHELVES.getCode());
        boolean update = couponService.update(couponWrapper);
        if (update) {
            return ResultBody.ok().message("上架优惠券成功");
        } else {
            return ResultBody.error().message("上架优惠券失败");
        }
    }

    /**
     * 下架优惠券
     *
     * @param couponId 优惠券Id
     * @return 下架优惠券情况
     */
    @ApiOperation(value = "下架优惠券", notes = "下架优惠券")
    @PostMapping(value = "/soldOutCoupon")
    public ResultBody soldOutAdvertising(@RequestParam String couponId) {
        LambdaUpdateWrapper<Coupon> couponWrapper = new LambdaUpdateWrapper<>();
        couponWrapper.eq(Coupon::getCouponId, couponId).set(Coupon::getStatus, CommonEnum.UN_SHELVES.getCode());
        boolean update = couponService.update(couponWrapper);
        if (update) {
            return ResultBody.ok().message("下架优惠券成功");
        } else {
            return ResultBody.error().message("下架优惠券失败");
        }
    }

    /**
     * 删除优惠券
     *
     * @param coupon 优惠券
     * @return 删除优惠券情况
     */
    @ApiOperation(value = "删除优惠券", notes = "删除优惠券")
    @PostMapping(value = "/deleteCoupon")
    public ResultBody deleteCoupon(@RequestBody Coupon coupon) {
        boolean delete = couponService.removeById(coupon.getCouponId());
        if (delete) {
            return ResultBody.ok().message("删除优惠券成功");
        } else {
            return ResultBody.error().message("删除优惠券失败");
        }
    }

    /**
     * 领取优惠券
     *
     * @param couponReceive 优惠券领取
     * @return 领取优惠券情况
     */
    @ApiOperation(value = "领取优惠券", notes = "领取优惠券")
    @PostMapping(value = "/receiveCoupon")
    public synchronized ResultBody receiveCoupon(@RequestBody CouponReceive couponReceive) {
        Long couponId = couponReceive.getCouponId();
        Coupon coupon = couponService.getById(couponId);
        if (coupon.getNum() >= 1) {
            if (deduction(coupon, couponReceive)) {
                coupon.setNum(coupon.getNum() - 1);
                couponService.updateById(coupon);
                couponReceive.setStatus(CommonEnum.UN_USED.getCode());
                couponReceive.setReceiveTime(new Date());
                boolean save = couponReceiveService.save(couponReceive);
                if (save) {
                    return ResultBody.ok().message("领取优惠券成功");
                } else {
                    return ResultBody.error().message("领取优惠券失败");
                }
            } else {
                return ResultBody.error().message("积分不足");
            }
        } else {
            return ResultBody.error().message("优惠券已领完");
        }
    }

    /**
     * 领取优惠券
     *
     * @param couponReceive 优惠券领取
     * @return 领取优惠券情况
     */
    @ApiOperation(value = "查询领取优惠券", notes = "查询领取优惠券")
    @PostMapping(value = "/queryCouponReceive")
    public ResultBody queryCouponReceive(@RequestBody CouponReceive couponReceive) {
        Long userId = couponReceive.getUserId();
        LambdaQueryWrapper<CouponReceive> couponReceiveWrapper = new LambdaQueryWrapper<>();
        couponReceiveWrapper.eq(CouponReceive::getUserId, userId)
                .eq(CouponReceive::getStatus, CommonEnum.UN_USED.getCode())
                .orderByDesc(CouponReceive::getReceiveTime);
        List<CouponReceive> list = couponReceiveService.list();
        if (list.size() >= 1) {
            return ResultBody.ok().data(list);
        } else {
            return ResultBody.error().message("暂无可使用的优惠券");
        }
    }

    /**
     * 获取需要下架的优惠券
     */
    @Scheduled(cron = "0 0/10 * * * ?")
    private void getUnshelveCouponList() {
        LambdaQueryWrapper<Coupon> couponWrapper = new LambdaQueryWrapper<>();
        couponWrapper.eq(Coupon::getStatus, CommonEnum.SHELVES.getCode()).lt(Coupon::getEndTime, DateUtil.today());
        List<Coupon> couponList = couponService.list(couponWrapper);
        if (!couponList.isEmpty()) {
            couponList.forEach(e -> unshelveCoupon(e.getCouponId()));
        }
    }

    /**
     * 优惠券失效
     *
     * @param couponId 优惠券Id
     */
    private void unshelveCoupon(Long couponId) {
        Coupon coupon = couponService.getById(couponId);
        if (coupon.getStatus().equals(CommonEnum.SHELVES.getCode())) {
            coupon.setStatus(CommonEnum.UN_SHELVES.getCode());
            couponService.updateById(coupon);
        }
    }


    /**
     * 获取需要失效的优惠券，并自动过期（每十分钟执行一次）
     */
    @Scheduled(cron = "0 0/10 * * * ?")
    private void getCancelCoupon() {
        LambdaQueryWrapper<CouponReceive> couponReceiveWrapper = new LambdaQueryWrapper<>();
        couponReceiveWrapper.eq(CouponReceive::getStatus, CommonEnum.UN_USED.getCode()).lt(CouponReceive::getEndTime, DateUtil.today());
        List<CouponReceive> couponReceiveList = couponReceiveService.list(couponReceiveWrapper);
        if (!couponReceiveList.isEmpty()) {
            couponReceiveList.forEach(e -> failureCoupon(e.getReceiveId()));
        }
    }

    /**
     * 优惠券失效
     *
     * @param receiveId 优惠券
     */
    private void failureCoupon(Long receiveId) {
        CouponReceive couponReceive = couponReceiveService.getById(receiveId);
        if (couponReceive.getStatus().equals(CommonEnum.UN_USED.getCode())) {
            couponReceive.setStatus(CommonEnum.DELAYED.getCode());
            couponReceiveService.updateById(couponReceive);
        }
    }

    /**
     * 积分兑换优惠券
     *
     * @param coupon 优惠券
     */
    private Boolean deduction(Coupon coupon, CouponReceive couponReceive) {
        LambdaQueryWrapper<UserDetail> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserDetail::getUserId, couponReceive.getUserId());
        UserDetail userDetail = userDetailService.getOne(wrapper);
        Integer userPoints = userDetail.getUserPoints();
        if (coupon.getReceiveType().equals(CommonEnum.POINT.getCode()) && userPoints >= coupon.getDeduction()) {
            userDetail.setUserPoints(userPoints - coupon.getDeduction());
            userDetailService.updateById(userDetail);
            return true;
        } else {
            return false;
        }
    }

}
